home *** CD-ROM | disk | FTP | other *** search
AMOS Source Code | 1992-09-29 | 19.6 KB | 455 lines |
- '*******************************************************
- '* *
- '* AMOS Professional Procedure Library *
- '* *
- '* Procedure: Radar Routine *
- '* *
- '* Author: Mike Stevens *
- '* *
- '*******************************************************
- '
- ' RADAR ROUTINE
- '
- ' and
- '
- ' A M O S
- ' * ** ****** ****** ** ** *****
- ' *** ** ** ** *** ** **
- ' ** * ** ** ***** ** * ** ****
- ' ******* ** ** ** ** * ** **
- ' ** * ** ** ** ** *** **
- ' ** * ****** ****** ****** ** ** *****
- '
- ' By Mike Stevens, Immortal Software 1992.
- '
- ' The main part to this program is the set of procedures which constitute
- 'the radar routine. With these, you can easily set up and operate a radar
- 'scanner for use in games. In order to put the radar procedures through their
- 'paces, I decided I would have to write a game which actually used them; and
- 'so AMOS ALIENS was born.
- '
- ' Instructions:
- ' Responding to a distress call from a space station, you and your crew
- ' boarded the vessel. The whole ship seemed derelict, as if no one had ever
- ' been there; until, that is, you stumbled across deck three...
- ' Corpses littered the floor, fresh blood lined the walls; it wasn't a
- ' pretty sight. You were so stunned, you didn't even notice the approaching
- ' creatures until they were on top of you. The rest of your crew were
- ' too slow; they were wiped out after the first attack. Luckily, you managed
- ' to survive. Now, armed with only your machine gun and movement detector,
- ' you must wipe out the alien horde.
- ' Due to the fact that your only light source is a small helmet-torch,
- ' you can only see, and fire within an area of 5 by 5 squares at any time.
- ' Your only hope lies in your radar, with which you can detect the movements
- ' of the enemy around you. Use the cursor keys to move, and the space bar
- ' to fire in the direction you are facing. You are represented by an 'O',
- ' the space station's walls by a '#' or a '*', and the aliens by a 'X'. The
- ' aliens aren't armed, but they're fast, and there are lots of them.
- '
- ' There are a couple of minor bugs in the game, most notably that since the
- 'walls are generated totally randomly, it is quite possible that you could be
- 'totally isolated from any or all of the aliens, making it impossible to
- 'complete. However, the basic game is quite fun, even with it's pathetic
- 'graphics, and it demonstrates the principle of how to use the radar. This
- 'little program has inspired me, and I intend to develop a more graphical,
- 'fully featured version...
- '
- '*************************************************************************
- '
- ' Set up some constants...
- _UP=0 : _DOWN=1 : _LEFT=2 : _RIGHT=3
- _MAPWID=25 : _MAPHGT=25 : _ALIENS=20
- ' Set up some initial values...
- _SCORE=0 : Rem ' 500 points per alien.
- _ALIENSKILLED=0 : Rem ' You win when you kill them all.
- _BLIPS=0 : Rem ' Number of aliens in scanner range.
- _PLYRX=10 : _PLYRY=10 : Rem ' Player starting co-ordinates.
- Dim _MAP$(_MAPWID-1,_MAPHGT-1) : Rem ' Main array, holding map data.
- Dim _ALIENX(_ALIENS-1),_ALIENY(_ALIENS-1) : Rem ' Aliens' co-ordinates array.
- Dim _BLIPX(_ALIENS),_BLIPY(_ALIENS) : Rem ' Scanner blips' co-ordinates array.
- Gosub _INITIALISE : Rem ' Set everything up.
- Gosub _DRAWGRID : Rem ' Draw the 5*5 main play area.
- ' Main game loop
- _DEAD=False
- Repeat
- Gosub _DRAWMAP : Rem ' Fill the grid with what you can see.
- ' Test for key presses...
- _MOVEUP=Key State($4C) : _MOVEDOWN=Key State($4D)
- _MOVELEFT=Key State($4F) : _MOVERIGHT=Key State($4E)
- _FIRE=Key State($40)
- ' For each direction the player tries to move in, check whether they can,
- ' and if so, move them. Keep track of LastMove, because this is the
- ' direction you fire in.
- If _MOVEUP and(_PLYRY>0) Then If(_MAP$(_PLYRX,_PLYRY-1)=" ") Then Dec _PLYRY : _LASTMOVE=_UP
- If _MOVEDOWN and(_PLYRY<_MAPHGT-1) Then If(_MAP$(_PLYRX,_PLYRY+1)=" ") Then Inc _PLYRY : _LASTMOVE=_DOWN
- If _MOVELEFT and(_PLYRX>0) Then If(_MAP$(_PLYRX-1,_PLYRY)=" ") Then Dec _PLYRX : _LASTMOVE=_LEFT
- If _MOVERIGHT and(_PLYRX<_MAPWID-1) Then If(_MAP$(_PLYRX+1,_PLYRY)=" ") Then Inc _PLYRX : _LASTMOVE=_RIGHT
- If _FIRE Then Gosub _SHOOT
- Gosub _ALIENMOVE : Rem ' Move them bad guys...
- Gosub _UPDATERADAR : Rem' The really neat bit.
- ' Go until either you're dead, or they are.
- Until _DEAD or _ALIENSKILLED=_ALIENS
- ' Display ending message.
- Locate 0,0 : Cline
- If _DEAD Then Centre "You're Dead" Else Centre "Congratulations- you killed all the aliens."
- End
- '
- _INITIALISE:
- ' This routine sets up the display, and map data.
- Screen Open 0,320,150,4,Lowres : Rem ' Screen 0 is main play area
- Flash Off : Curs Off : Cls 0
- Pen 1 : Paper 0
- Locate 0,0 : Centre "AMOS ALIENS"
- Palette 0,$FFF,$555,$1AF
- Screen Open 1,320,50,16,Lowres : Rem ' Screen 1 is status panel (score & radar)
- Screen Display 1,,200,,
- Flash Off : Curs Off : Cls 0
- Colour 0,$222
- Pen 14 : Paper 0
- Locate 20,1 : Print "AMOS ALIENS"
- ' Set up the radar for 12 colours, green display on screen 1.
- _MAKE_RADAR_COLOURS[12,$10]
- _RADAR_DRAW[40,25,25,12,6,0]
- ' Initialise walls on the space station.
- For Y=0 To _MAPHGT-1
- For X=0 To _MAPWID-1
- If Rnd(3)=0 Then _MAP$(X,Y)="#" Else _MAP$(X,Y)=" "
- Next X
- Next Y
- _MAP$(_PLYRX,_PLYRY)=" " : Rem ' Make sure player doesn't start on a wall.
- Return
- '
- _DRAWGRID:
- ' This routine uses AMOS graphics characters to draw a 5*5 display grid.
- Screen 0
- Pen 3 : Paper 0
- _TLY=6 : _TLX=13 : Rem ' This is the position of the grid from the top left of the screen.
- ' This messy chunk draws the grid using characters. On second thoughts,
- 'I'd probably have been better off drawing it using graphics commands.
- For X=1 To 9
- Locate _TLX+X,0+_TLY
- If X mod 2 Then Print Chr$($89); Else Print Chr$($8E);
- Locate _TLX+X,10+_TLY
- If X mod 2 Then Print Chr$($89); Else Print Chr$($8F);
- For Y=1 To 9
- Locate _TLX+X,_TLY+Y
- If(X mod 2)
- If(Y mod 2)=0 : Print Chr$($89); : End If
- Else
- If(Y mod 2) : Print Chr$($8B)
- Else Print Chr$($92)
- End If
- End If
- Next Y
- Next X
- For Y=1 To 9
- Locate _TLX,_TLY+Y
- If Y mod 2 Then Print Chr$($8B); Else Print Chr$($90);
- Locate _TLX+10,_TLY+Y
- If Y mod 2 Then Print Chr$($8B); Else Print Chr$($91);
- Next Y
- Locate _TLX,_TLY : Print Chr$($88);
- Locate _TLX+10,_TLY : Print Chr$($8A);
- Locate _TLX,_TLY+10 : Print Chr$($8C);
- Locate _TLX+10,_TLY+10 : Print Chr$($8D);
- ' Randomly position all the aliens.
- For I=1 To _ALIENS
- X=Rnd(_MAPWID-1) : Y=Rnd(_MAPHGT-1)
- ' Keep randomly generating co-ordinates until we land in an empty square.
- While _MAP$(X,Y)<>" " or X=_PLYRX or Y=_PLYRY
- X=Rnd(_MAPWID-1) : Y=Rnd(_MAPHGT-1)
- Wend
- ' Put the alien on the map.
- _MAP$(X,Y)="X"
- _ALIENX(I-1)=X : _ALIENY(I-1)=Y
- Next I
- ' Set up drawing colours for rest of program.
- Pen 1 : Paper 0
- Return
- '
- _DRAWMAP:
- ' This routine fills the grid with the visible contents of the array _MAP$
- 'for an area 5*5 characters big, centred on the player's current position.
- For Y=_PLYRY-2 To _PLYRY+2
- For X=_PLYRX-2 To _PLYRX+2
- Locate _TLX+5+(X-_PLYRX)*2,_TLY+5+(Y-_PLYRY)*2
- ' If we're at the edges of the map, don't attempt to draw non-existant
- 'array elements; just display a "*" for the map boundary.
- If X<0 or Y<0 or X>_MAPWID-1 or Y>_MAPHGT-1 Then Print Pen$(2)+"*"+Pen$(1); Else Print _MAP$(X,Y);
- Next X
- Next Y
- ' Draw the player on screen.
- Locate _TLX+5,_TLY+5 : Print "O";
- ' And draw the score on the status panel.
- Gosub _UPDATESCORE
- Return
- '
- _SHOOT:
- ' This procedure deals with what happens when the space bar is pressed.
- ' Set up the displacements by which the bullet will move.
- If _LASTMOVE=_UP Then X=0 : Y=-1
- If _LASTMOVE=_DOWN Then X=0 : Y=1
- If _LASTMOVE=_LEFT Then X=-1 : Y=0
- If _LASTMOVE=_RIGHT Then X=1 : Y=0
- ' Start from the square the player is standing in.
- _SHOTX=_PLYRX : _SHOTY=_PLYRY
- Shoot : Rem ' Make a noise.
- ' Since only two squares are visible in any direction, we only need to
- 'move the bullet twice at most.
- For I=0 To 1
- ' Move the bullet to it's new square.
- Add _SHOTX,X : Add _SHOTY,Y
- ' If it's gone off the map, exit the loop.
- If _SHOTX<0 or _SHOTY<0 or _SHOTX>_MAPWID-1 or SHOTY>_MAPHGT-1 Then Exit
- ' If it's hit a wall, exit the loop (bullets can't travel through walls).
- If _MAP$(_SHOTX,_SHOTY)="#" Then Exit
- ' If it's hit an alien, then kill him, and add to the player's score and kills.
- If _MAP$(_SHOTX,_SHOTY)="X" Then Boom : _MAP$(_SHOTX,_SHOTY)=" " : Add _SCORE,500 : Inc _ALIENSKILLED : Gosub _UPDATESCORE
- ' If it's in an empty square, draw the bullet, wait a few seconds, then go on.
- If _MAP$(_SHOTX,_SHOTY)=" " Then Locate _TLX+5+(_SHOTX-_PLYRX)*2,_TLY+5+(_SHOTY-_PLYRY)*2 : Print "."; : Wait 5 : Print Cleft$+" ";
- Next I
- Return
- '
- _ALIENMOVE:
- ' This procedure moves the aliens about the map at random.
- ' Do this for each alien.
- For I=0 To _ALIENS-1
- ' Only do this if the alien is still alive.
- If _MAP$(_ALIENX(I),_ALIENY(I))="X"
- ' Erase the alien at his last position.
- _MAP$(_ALIENX(I),_ALIENY(I))=" "
- ' Generate a random direction. NB There is a 50% chance of the alien
- 'not moving at all. If they always move, then the game is far too
- 'difficult, as they're just too quick.
- DRCTN=Rnd(8)
- ' Check that the chosen direction is viable, and if so move the alien
- 'to the new square.
- ' NB I know that block If..Else...EndIf statements would run faster
- 'here, but they just make the code so messy in AMOS. If only AMOS had
- 'an ElseIf clause, like AmigaBASIC.
- If DRCTN=0 and _ALIENY(I)>0 : If _MAP$(_ALIENX(I),_ALIENY(I)-1)<>"#" : Dec _ALIENY(I) : End If : End If
- If DRCTN=1 and _ALIENY(I)<_MAPHGT-1 : If _MAP$(_ALIENX(I),_ALIENY(I)+1)<>"#" : Inc _ALIENY(I) : End If : End If
- If DRCTN=2 and _ALIENX(I)>0 : If _MAP$(_ALIENX(I)-1,_ALIENY(I))<>"#" : Dec _ALIENX(I) : End If : End If
- If DRCTN=3 and _ALIENX(I)<_MAPWID-1 : If _MAP$(_ALIENX(I)+1,_ALIENY(I))<>"#" : Inc _ALIENX(I) : End If : End If
- ' Redraw the alien at his new home.
- _MAP$(_ALIENX(I),_ALIENY(I))="X"
- ' If he's collided with the player, it's all over...
- If _ALIENX(I)=_PLYRX and _ALIENY(I)=_PLYRY : Gosub _DRAWMAP : Boom : _DEAD=True : End If
- End If
- Next I
- Return
- '
- _UPDATERADAR:
- ' This routine shows how to make use of the _PLOT_BLIP instruction.
- Screen 1 : Rem ' First switch to the radar screen.
- ' Before drawing new blips, we have to erase the old ones. The BLIPS and
- 'BLIPX,BLIPY variables store all the information from last time around the
- 'loop.
- While _BLIPS
- ' Erase this blip, then go on to the next one.
- _PLOT_BLIP_RECT[_BLIPX(_BLIPS-1)*3,_BLIPY(_BLIPS-1)*3]
- Dec _BLIPS
- Wend
- ' Scan a 25*25 square area around the player for aliens.
- For Y=_PLYRY-5 To _PLYRY+5
- For X=_PLYRX-5 To _PLYRX+5
- ' Don't try and access non-existant array elements if we're at the
- 'map's boundary...
- If Y>=0 and Y<_MAPHGT and X>=0 and X<_MAPWID
- ' If we've found an alien, record it in the blips variables, and
- 'go on checking the other squares.
- If _MAP$(X,Y)="X"
- _BLIPX(_BLIPS)=X-_PLYRX : _BLIPY(_BLIPS)=Y-_PLYRY
- Inc _BLIPS
- End If
- End If
- Next X
- Next Y
- ' Play a beep which gets higher in pitch, the more aliens there are on the
- 'scanner (adds to the tension).
- If _BLIPS Then Sam Play %11,1,_BLIPS*1000+5000
- ' Now plot all the new blips on the radar.
- I=_BLIPS
- While I
- ' I'm using a *3 multiplier, since the actual pixel distances would be
- 'too small for the scanner to be used effectively.
- _PLOT_BLIP_RECT[_BLIPX(I-1)*3,_BLIPY(I-1)*3]
- Dec I
- Wend
- ' Return to the main playing screen.
- Screen 0
- Return
- '
- _UPDATESCORE:
- ' Switch to the status panel (screen1) and print the score...
- Screen 1
- Locate 20,3
- Pen 14 : Paper 0
- Print "Score :";Str$(_SCORE);
- Screen 0
- Return
- '
- '
- ' RADAR PROCEDURES
- '
- Procedure _RADAR_DRAW[X,Y,R,SEGS,SPEED,_DIRECTION]
- Shared _RADARX,_RADARY,_RADARSIZE
- '
- ' Inputs...
- ' X,Y - The co-ordinates of the centre of the radar.
- ' R - The circular radius of the radar (in pixels).
- ' SEGS- The number of segments to chop the radar into. The smaller
- ' this value, the fewer colours are used up by the radar. The
- ' higher this value, the smoother the animation of the radar.
- ' 12 is about the practical minimum.
- ' SPEED-The speed at which the radar animates.
- ' _DIRECTION- The direction in which the radar 'arm' spins.
- ' 0=clockwise, 1=anticlockwise.
- '
- ' **************************
- '
- ' Shared variables...
- ' _RADARX,_RADARY - These are initialised to the X and Y values passed
- ' to the procedure, to enable the BLIP procedures to plot blips
- ' relative to the origin of the radar.
- ' _RADARSIZE - This is initialised to the R value passed to this
- ' procedure, and is used for range checking in the BLIP procedures.
- '
- ' **************************
- '
- ' External stuff...
- ' This procedure uses the AMOS maths functions, so requires the
- ' mathtrans.library to be in the LIBS: directory of your boot disk.
- '
- ' **************************
- '
- Degree : Rem ' I can't work in radians.
- Circle X,Y,R : Rem ' Draw the outline of the radar.
- _RDR_STEP=360/SEGS : Rem ' Calculate the angular step.
- ' Now for the mathematical bit...
- ' This loop divides the circle up into segments by drawing two arcs
- ' to the circumference from the origin. The loop index is theta, the
- ' bearing from the line SO (which goes from the south point of the circle
- ' to the origin). Using trigonometry, we work out the co-ords (X1,Y1) where
- ' the first arc meets the circumference, and (X2,Y2) where the second arc
- ' meets the circumference. These co-ords are relative to the circle's
- ' origin. We then outline the segment, and get the co-ords of a point
- ' somewhere in the middle of this segment (XFILL,YFILL), and do a flood
- ' fill. Doing this with successively brighter shades of the same colour
- ' makes a pretty, graduated colour fill, which can then be rotated using
- ' the shift up command.
- For _RDR_THETA=0 To 360-(2*_RDR_STEP-1) Step _RDR_STEP
- X1=R*Sin(_RDR_THETA) : Y1=R*Cos(_RDR_THETA)
- X2=R*Sin(_RDR_THETA+_RDR_STEP) : Y2=R*Cos(_RDR_THETA+_RDR_STEP)
- If _DIRECTION=0 Then Ink(360-(2*_RDR_STEP-1)-_RDR_THETA)/_RDR_STEP+2 Else Ink _RDR_THETA/_RDR_STEP+1
- Polyline X+X1,Y+Y1 To X,Y To X+X2,Y+Y2
- XFILL=X+(X1+X2)/2 : YFILL=Y+(Y1+Y2)/2
- Paint XFILL,YFILL,1
- Next _RDR_THETA
- ' Due to inaccuracies in calculation, we don't draw the arc boundaries
- ' for the last segment. Since they're already there, we simply fill the
- ' hole.
- If _DIRECTION=0 Then Ink(360-(2*_RDR_STEP-1)-_RDR_THETA)/_RDR_STEP+1 Else Ink _RDR_THETA/_RDR_STEP+1
- X1=0 : Y1=R
- XFILL=X+(X1+X2)/2 : YFILL=Y+(Y1+Y2)/2
- Paint XFILL,YFILL
- ' Finally, erase the circle outline, and the radar is complete.
- Ink 0
- Circle X,Y,R
- ' Now animate it.
- Shift Up SPEED,1,SEGS,1
- _RADARX=X : _RADARY=Y : _RADARSIZE=R
- End Proc
- '
- Procedure _PLOT_BLIP[THETA,R]
- Shared _RADARX,_RADARY,_RADARSIZE
- '
- ' Inputs...
- ' THETA, R - The polar co-ordinates of the position of the blip you
- ' want to plot, relative to the centre of the radar.
- '
- ' **************************
- '
- ' Shared variables...
- ' _RADARX,_RADARY - These are initialised to the X and Y values passed
- ' to the procedure, to enable the BLIP procedures to plot blips
- ' relative to the origin of the radar.
- ' _RADARSIZE - This is initialised to the R value passed to this
- ' procedure, and is used for range checking in the BLIP procedures.
- '
- ' **************************
- '
- ' NB To plot a blip, call this procedure. If you want to move the blip, you
- ' must call this procedure to unplot the first blip, then call it again to
- ' reposition. Look at the demo program (the _UPDATE_RADAR subroutine) to see
- ' how this should be done. You must also switch to the screen on which the
- ' radar has been drawn before calling this procedure.
- '
- If R>_RADARSIZE Then Pop Proc : Rem ' Don't plot if beyond bounds of radar.
- ' Calculate the screen co-ords of the centre of the blip.
- X=_RADARX+R*Sin(THETA) : Y=_RADARY+R*Cos(THETA)
- ' Set to XOR mode.
- Gr Writing 2 : Ink 31
- ' Draw blip as a + symbol. Can anyone think of a better way of doing it?
- Plot X,Y : Plot X+1,Y : Plot X,Y+1
- Plot X-1,Y : Plot X,Y-1
- End Proc
- '
- Procedure _PLOT_BLIP_RECT[X,Y]
- Shared _RADARX,_RADARY,_RADARSIZE
- '
- ' Inputs...
- ' X, Y - The cartesian co-ordinates of the position of the blip you
- ' want to plot, relative to the centre of the radar.
- '
- ' **************************
- '
- ' Shared variables...
- ' _RADARX,_RADARY - These are initialised to the X and Y values passed
- ' to the procedure, to enable the BLIP procedures to plot blips
- ' relative to the origin of the radar.
- ' _RADARSIZE - This is initialised to the R value passed to this
- ' procedure, and is used for range checking in the BLIP procedures.
- '
- ' **************************
- '
- ' NB This procedure is identical to _PLOT_BLIP, except that it uses cartesian
- ' (X,Y) co-ordinates, rather than polar (R,�) co-ords. See the notes for
- ' _PLOT_BLIP.
- '
- R=Sqr(X*X+Y*Y) : Rem ' Use pythagoras to calculate the R component of the co-ords.
- If R>_RADARSIZE Then Pop Proc : Rem ' If it lies out of bounds, then don't plot it.
- ' Calculate screen co-ords of centre of blip.
- X=X+_RADARX : Y=Y+_RADARY
- Gr Writing 2 : Ink 31
- Plot X,Y : Plot X+1,Y : Plot X,Y+1
- Plot X-1,Y : Plot X,Y-1
- End Proc
- '
- Procedure _MAKE_RADAR_COLOURS[NUM,MASK]
- '
- ' Inputs...
- ' NUM - Number of colours to calculate.
- ' MASK - An RGB shading mask used to create the colour range.
- '
- ' **************************
- '
- ' NB This procedure knocks up a spread of colours using colours 1 to NUM,
- ' from dark to light, using a simple algorithm of multiplying an intensity
- ' by the provided RGB mask. Call this directly before calling _MAKE_RADAR.
- ' Give the same value for SEGS in _MAKE_RADAR as for NUM here.
- ' You could, of course, forget this procedure altogether and just knock up
- ' your own colours for the radar.
- ' Example values for this mask: (don't forget the $ sign)
- ' $1 - Creates a Blue radar.
- ' $10 - " " Green " .
- ' $100 - " " Red " .
- ' $11 - Creates a Turquoise (Cyan) radar.
- ' $101 - " " Purple radar.
- ' $110 - " " Yellow " .
- ' $111 - " " Grey " .
- '
- For _RDR_INDEX=1 To NUM
- Colour _RDR_INDEX,(_RDR_INDEX-1)*MASK
- Next _RDR_INDEX
- End Proc